﻿using Microsoft.Extensions.Logging;
using Photo.Application.System.User.Dto;

namespace Photo.Application.System.User
{
    /// <summary>
    /// 系统用户
    /// </summary>
    [ApiDescriptionSettings(ApiGroupConsts.System, Module = ApiGroupConsts.System)]
    public class UserService : IDynamicApiController
    {
        private readonly IRepository<SysUserEntity> _sysUserRepository;
        private readonly IRepository<SysRoleEntity> _sysRoleRepository;
        private readonly IRepository<SysUserRoleEntity> _sysUserRoleRepository;
        public UserService(IRepository<SysUserEntity> sysUserRepository, IRepository<SysRoleEntity> sysRoleRepository, IRepository<SysUserRoleEntity> sysUserRoleRepository)
        {
            _sysUserRepository = sysUserRepository;
            _sysRoleRepository = sysRoleRepository;
            _sysUserRoleRepository = sysUserRoleRepository;
        }

        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [UnitOfWork]
        public async Task Add(UserSaveInput input)
        {
            await MutexUtil.MutexNoWait("/api/system/user/add", async () =>
            {
                if (string.IsNullOrWhiteSpace(input.Password))
                    throw Oops.Oh("新增用户需要输入密码");
                if (await _sysUserRepository.AnyAsync(o => o.Account == input.Account))
                    throw Oops.Oh("用户账号重复");

                var entity = input.Adapt<SysUserEntity>();
                entity.Password = MD5Encryption.Encrypt(input.Password);

                await _sysUserRepository.InsertAsync(entity);

                var roleIds = input.RoleIds?.Split(",", StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>();
                var userRoleList = roleIds.Select(o => new SysUserRoleEntity
                {
                    UserId = entity.Id,
                    RoleId = o
                }).ToList();

                await _sysUserRoleRepository.InsertAsync(userRoleList);

            });
        }

        /// <summary>
        /// 修改用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task Edit(UserSaveInput input)
        {
            await MutexUtil.MutexNoWait("/api/system/user/edit", async () =>
            {
                if (await _sysUserRepository.AnyAsync(o => o.Id != input.Id && o.Account == input.Account))
                    throw Oops.Oh("用户账号重复");

                var entity = await _sysUserRepository.GetAsync(input.Id, "当前用户不存在");
                entity.Account = input.Account;
                entity.Password = !string.IsNullOrWhiteSpace(input.Password) ? MD5Encryption.Encrypt(input.Password) : entity.Password;
                entity.IsActive = input.IsActive;

                await _sysUserRepository.UpdateAsync(entity);

                //先删除原有角色关联
                await _sysUserRoleRepository.DeleteAsync(o => o.UserId == entity.Id);

                //再添加新的角色关联
                var roleIds = input.RoleIds?.Split(",", StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>();
                var userRoleList = roleIds.Select(o => new SysUserRoleEntity
                {
                    UserId = entity.Id,
                    RoleId = o
                }).ToList();

                await _sysUserRoleRepository.InsertAsync(userRoleList);
            });
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [UnitOfWork]
        public async Task Del(PrimaryKey input)
        {
            await MutexUtil.MutexNoWait("/api/system/user/del", async () =>
            {
                //1.删除用户信息
                var entity = await _sysUserRepository.GetAsync(input.Id, "当前用户不存在");
                await _sysUserRepository.DeleteAsync(entity);

                //2.删除用户角色关联记录
                await _sysUserRoleRepository.DeleteAsync(o => o.UserId == entity.Id);
            });
        }

        /// <summary>
        /// 设置用户有效性
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SetActive(PrimaryKey input)
        {
            await MutexUtil.MutexNoWait("/api/system/user/setactive", async () =>
            {
                var entity = await _sysUserRepository.GetAsync(input.Id, "当前用户不存在");

                entity.IsActive = !entity.IsActive;

                await _sysUserRepository.UpdateAsync(entity);
            });
        }

        /// <summary>
        /// 获取用户分页列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedList<UserOutput>> GetPagedList(UserPagedInput input)
        {
            var roleIds = input.RoleIds?.Split(",", StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<string>();
            var list = await _sysUserRepository.Query()
                .WhereIF(!string.IsNullOrWhiteSpace(input.KeyWord), o => o.Account.Contains(input.KeyWord))
                .WhereIF(input.IsActive.HasValue, o => o.IsActive == input.IsActive)
                .WhereIF(roleIds.Count > 0, o => SqlFunc.Subqueryable<SysUserRoleEntity>().Where(x => roleIds.Contains(x.RoleId)).Where(x => x.UserId == o.Id).Any())
                .OrderByIF(!string.IsNullOrWhiteSpace(input.OrderByField), input.OrderByField)
                .Select<UserOutput>()
                .ToPagedListAsync(input);

            var userIds = list.List.Select(o => o.Id).ToList();
            var userRoleList = await _sysUserRoleRepository.GetFieldListAsync(o => userIds.Contains(o.UserId), o => new { o.RoleId, o.UserId }, o => o.CreationTime);
            var userRoleIds = userRoleList.Select(o => o.RoleId).Distinct().ToList();
            var roleNameList = await _sysRoleRepository.GetFieldListAsync(o => userRoleIds.Contains(o.Id), o => new { o.Id, o.Name }, o => o.Sort);

            list.List.ForEach(item =>
            {
                var curUserRoleIds = userRoleList.Where(o => o.UserId == item.Id).Select(o => o.RoleId).Distinct().ToList();
                item.RoleName = roleNameList.Where(o => curUserRoleIds.Contains(o.Id)).Select(o => o.Name).Distinct().Join(",");
            });
            return list;
        }

        /// <summary>
        /// 获取用户详情
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<UserDto> GetInfo(PrimaryKey input)
        {
            var info = await _sysUserRepository.GetAsync<UserDto>(input.Id);
            info.RoleIds = await _sysUserRoleRepository.GetFieldDistinctListAsync(o => o.UserId == info.Id, o => o.RoleId);
            return info;
        }

    }
}
